<template>
  <div class="feedback" v-if="showFeedback || canRating || managerShowFeedBack">
    <!-- <div class="feedback-left"> -->
    <!-- <div> -->
    <v-button
      class="h26"
      v-if="webIMSource === 'workbench' && finishWs"
      @click="onSendSearchMsg"
      size="small"
      kind="primary"
      >发送</v-button
    >
    <v-button
      class="h26"
      v-if="webIMSource === 'workbench' && finishWs"
      @click="onCopySearchMsg"
      size="small"
      >复制到输入框</v-button
    >
    <v-button
      class="h26"
      v-if="webIMSource === 'workbench' && !finishWs"
      @click="onStopStream"
      size="small"
      >停止生成</v-button
    >
    <v-button
      class="h26"
      :disabled="hadRetryQa && connectionError"
      v-if="
        (showReGenerateBtn || connectionError) &&
        msgData.reply_method !== 16 &&
        msgData.reply_method !== 9 &&
        msgData.reply_method !== 10
      "
      @click="onRetryQa"
      size="small"
      >重新生成</v-button
    >
    <v-button
      class="h26"
      v-if="
        webIMSource === 'manage' &&
        finishWs &&
        msgData.reply_method !== 4 &&
        msgData.reply_method !== 8 &&
        msgData.reply_method !== 9 &&
        msgData.reply_method !== 10 &&
        appType !== APP_TYPE.SUMMARY &&
        appType !== APP_TYPE.CLASSIFYS &&
        !isMLLMQa
      "
      @click="onAuditQa"
      size="small"
      >修正</v-button
    >
    <v-button
      class="h26"
      v-if="isDownActive"
      @click="onOpenFeedback"
      size="small"
      >去反馈</v-button
    >
    <!-- </div> -->
    <span v-if="connectionError" class="connection-error"
      >网络异常，请重新生成</span
    >
    <!-- </div> -->
    <template
      v-if="
        (showFeedback || is_llm_generated || canRating || showAITips) &&
        finishWs
      "
    >
      <span
        v-tip:voice.hover
        v-if="showTTSButton && webIMSource !== 'workflow'"
        class="read-history-msg"
        @click="readMsg"
      >
        <!-- <img v-if="isPlaying" class="opt" src="@/assets/img/volume.png" /> -->
        <!-- <v-icon v-else class="opt"  size="20" name="basic_volume_line" remote /> -->
        <v-icon class="opt" size="20" name="basic_volume_line" remote />
        <v-tip
          ref="voice"
          :disabled="isMobile || isVoicePlayDisable"
          placement="top"
          >{{ isPlaying ? "停止" : "开始" }}播报</v-tip
        >
      </span>
      <v-icon
        v-if="
          showCopyText && !(msgData.reply_method === 17 && !msgData.content)
        "
        remote
        name="basic_copy_line"
        size="20"
        class="opt"
        :class="['opt', { 'opt-mobile': isMobile }]"
        @click="onCopyMsg()"
      ></v-icon>
      <div v-if="showFeedback" style="display: flex">
        <v-icon
          v-tip:feedback.hover
          remote
          name="basic_questionaire_line"
          size="20"
          :class="['opt', { disabled: disableFeedback }]"
          @click="openFeedback"
        ></v-icon>
        <v-tip :disabled="disableFeedback" ref="feedback" placement="top-start"
          >提交反馈</v-tip
        >
      </div>
      <div v-if="showAITips" style="display: flex">
        <v-icon
          remote
          name="basic_tips_line"
          size="20"
          :class="['opt', { 'opt-mobile': isMobile }]"
          v-tip:info.hover
        ></v-icon>
        <v-tip ref="info" placement="top-start"
          >该答案由AI助手产生，请谨慎鉴别</v-tip
        >
      </div>
      <div
        v-if="(showFeedback || is_llm_generated) && canRating"
        class="spliter"
      ></div>
      <v-icon
        v-if="canRating"
        remote
        :name="isUpActive ? 'basic_thumbsup_fill' : 'basic_thumbsup_line'"
        size="20"
        :class="['opt', { disabled: isUpActive || isDownActive }]"
        @click="onFeedback(true)"
      ></v-icon>
      <v-icon
        v-if="canRating"
        remote
        :name="isDownActive ? 'basic_thumbsdown_fill' : 'basic_thumbsdown_line'"
        size="20"
        :class="['opt', { disabled: isUpActive || isDownActive }]"
        @click="onFeedback(false)"
      ></v-icon>
    </template>

    <!-- 用户端 - 点踩原因反馈弹窗 -->
    <Popup
      class="feedback-popup"
      v-if="feedbackPopupVisible"
      title="你的反馈将帮助应用服务优化进步"
      confirmText="提交"
      :showCloseIcon="true"
      :showCancelBtn="false"
      @confirm="submitReason"
      @cancel="feedbackPopupVisible = false"
    >
      <div :class="['feedback-tag-list', { isMobile: isMobile }]">
        <div
          class="feedback-tag-item"
          v-for="(item, index) in tagList"
          :key="index"
          @click="checkTag(item)"
        >
          <div class="feedback-tag-title">{{ item.title }}</div>
          <v-tags
            :value="item.children"
            :selectable="true"
            v-model="selectedTag"
            :maps="{ value: 'id', text: 'name' }"
            size="large"
          ></v-tags>
        </div>
      </div>
    </Popup>

    <!-- 坐席端 - 点踩原因反馈弹窗 -->
    <v-dialog
      class="feedback-dlg"
      v-model="feedbackPopupWorkbenchVisible"
      kind="modal"
      title="你的反馈将帮助应用服务优化进步"
      @confirm="submitReason"
      @cancel="feedbackPopupWorkbenchVisible = false"
      confirmText="提交"
    >
      <div class="feedback-tag-list">
        <div
          class="feedback-tag-item"
          v-for="(item, index) in tagList"
          :key="index"
          @click="checkTag(item)"
        >
          <div class="feedback-tag-title">{{ item.title }}</div>
          <v-tags
            :value="item.children"
            :selectable="true"
            v-model="selectedTag"
            :maps="{ value: 'id', text: 'name' }"
            size="large"
          ></v-tags>
        </div>
      </div>
    </v-dialog>
  </div>
</template>

<script>
import copy from "copy-to-clipboard";
import Popup from "@/components/Popup";
import { getQueryVariable, processAndCopyContent } from "@/utils/util";
import { FEEDBACK_TAG_LIST, APP_TYPE } from "@/constants";
function containsImage(mdString) {
  // 正则表达式匹配 Markdown 中的图片格式
  const regex = /!\[.*\]\(.*\.(jpg|jpeg|png|gif|bmp)\)/g;
  return regex.test(mdString);
}
/**
 * 各状态说明
 * 展示本组件的条件：1. 实时会话  2. 历史记录 & 允许评分（非人工）
 * 展示”停止生成“的条件：数据流未结束
 * 展示”重新生成“的条件：已“点踩”
 * 展示”去反馈“的条件：已“点踩”
 * 展示”点踩/点踩“的条件：1. 实时会话 & 数据流已结束  2. 历史记录 & 允许评分（非人工）
 */
export default {
  name: "Feedback",
  components: {
    Popup,
  },
  props: {
    msgData: {
      type: Object,
      default: null,
    },
    msgList: {
      type: Array,
      default: () => [],
    },
    showCopyText: {
      type: Boolean,
      default: true,
    },
  },
  computed: {
    showReGenerateBtn() {
      return this.isDownActive && this.finishWs;
    },
    showFeedback() {
      return this.canFeedback && !this.hideFeedback;
    },
    showAITips() {
      return (
        this.msgData.is_llm_generated ||
        ((this.msgData.reply_method === 9 ||
          this.msgData.reply_method === 10 ||
          this.msgData.reply_method === 16 ||
          this.msgData.reply_method === 17) &&
          this.msgData.task_flow &&
          this.msgData.task_flow.type === 0)
      );
    },
    isMLLMQa() {
      // 是否多模态问答
      const question = this.msgList.find(
        (msg) => msg.record_id === this.msgData.related_record_id
      );
      if (question) {
        return (
          (question.file_infos && question.file_infos.length > 0) ||
          containsImage(question.content)
        );
      }
      return false;
    },
    managerShowFeedBack() {
      return (
        this.webIMSource === "manage" &&
        this.msgData.reply_method !== 6 &&
        this.msgData.reply_method !== 7
      );
    },
  },
  data() {
    const { is_reading, record_id } = this.$clientData.getReadStatus();
    const a =
      this.webIMSource === "client"
        ? window.localStorage.getItem("app_type")
        : getQueryVariable("app_type");
    return {
      isVoicePlayDisable: false,
      isPlaying: is_reading && record_id === this.msgData.record_id,
      showTTSButton: false,
      msgId: "", // 消息id
      related_record_id: "", // 答案关联的问题id
      finishWs: true, // 在流失输出完成后，再展示重新生成/去反馈/点赞/点踩
      isHistory: false, // 是否历史数据
      canRating: true, // 会否允许点赞/点踩 （不允许评分表示完全不显示点赞点踩按钮，目前是指非机器人消息）
      canFeedback: false,
      ratingScore: 0, // 点赞/点踩状态   0 - 未点赞/点踩  1 - 点赞  2 - 点踩
      isUpActive: false, // 是否已操作点赞
      isDownActive: false, // 是否已操作点踩
      feedbackPopupVisible: false, // 用户端 - 反馈原因弹窗
      feedbackPopupWorkbenchVisible: false, // 坐席端 - 反馈原因弹窗
      tagList: FEEDBACK_TAG_LIST,
      selectedTag: [], // 选中的反馈原因列表
      is_llm_generated: false, // 是否为模型生成内容
      connectionError: false, // ws链接异常
      hideFeedback: false,
      disableFeedback: false,
      appType: a || APP_TYPE.QA,
      APP_TYPE,
    };
  },
  created() {
    this.$eventHub.$on("stop_stream", (res) => {
      this.onStopStream();
    });
    this.$eventHub.$on("feedback_success", (record_id) => {
      if (this.msgId === record_id) {
        this.disableFeedback = true;
      }
    });
    this.$eventHub.$on("voice_input", ({ isRecording }) => {
      this.isVoicePlayDisable = isRecording;
    });
    this.hideFeedback = getQueryVariable("hideFeedback") === "true";
    this.buildData(this.msgData); // 历史数据构建
    this.$eventHub.$on("reading_audio", () => {
      const { is_reading, record_id } = this.$clientData.getReadStatus();
      if (is_reading && record_id === this.msgData.record_id) {
        this.isPlaying = true;
      } else {
        this.isPlaying = false;
      }
    });
    const cachedConfig = this.$clientData.getConfigInfo();
    if (cachedConfig && cachedConfig.ai_call) {
      this.showTTSButton = cachedConfig.ai_call.enable_voice_interact;
    }
    this.$eventHub.$on("client_configChange", (res) => {
      res.ai_call && (this.showTTSButton = res.ai_call.enable_voice_interact);
    });
    this.$eventHub.$on("ai_config_change", (res) => {
      this.showTTSButton = res.aiconfig.enable_voice_interact;
      const cachedConfig = this.$clientData.getConfigInfo();
      if (cachedConfig && cachedConfig.ai_call) {
        cachedConfig.ai_call.enable_voice_interact = this.showTTSButton;
      }
    });
  },
  watch: {
    msgData(newVal) {
      this.buildData(newVal); // 监听实时新消息变更，重新构建数据
    },
  },
  methods: {
    stopReading() {
      // 停止播放
      this.isPlaying = false;
      this.$eventHub.$emit("reading_audio", {
        reading: false,
        msg: this.msgData,
      });
    },
    readMsg() {
      if (this.isVoicePlayDisable) {
        return;
      }
      if (!this.isPlaying) {
        this.isPlaying = true;
        this.$eventHub.$emit("reading_audio", {
          reading: false,
        });
        this.$eventHub.$emit("reading_audio", {
          reading: true,
          msg: this.msgData,
        });
      } else {
        this.stopReading();
      }
    },
    openFeedback() {
      if (this.disableFeedback) {
        return;
      }
      try {
        const question = this.msgList.find(
          (msg) => msg.record_id === this.msgData.related_record_id
        );
        const payload = JSON.stringify({
          from: "webim",
          type: "feedback",
          question,
          answer: this.msgData,
        });
        window.parent.postMessage(payload, "*");
      } catch (error) {
        console.error("关联反馈问题及答案失败", this.msgData);
        const payload = JSON.stringify({
          from: "webim",
          type: "feedback",
          question: {},
          answer: this.msgData,
        });
        window.parent.postMessage(payload, "*");
      }
    },
    async onFeedback(isThumbsUp) {
      if (this.isUpActive || this.isDownActive) {
        // 已经点赞/点踩过，则不再支持点击
        return;
      }
      const toastWapper =
        this.webIMSource === "client" && !this.isMobile
          ? document.querySelector(".chat-wrap")
          : document.body;
      this.$toast({
        message: "感谢你的反馈",
        duration: 3,
        tdom: toastWapper,
        type: "success",
      });

      if (this.webIMSource === "workbench") {
        this.$socket.emit("rating", {
          record_id: this.msgId,
          score: isThumbsUp ? 1 : 2, // 1. 点赞, 2. 点踩
          reason: "",
        });

        if (isThumbsUp) {
          this.isUpActive = true;
        } else {
          this.isDownActive = true;
        }
      } else {
        // 前端消息队列数据打标点赞/点踩
        this.$clientData.triggerScore(this.msgId, isThumbsUp);
      }
    },
    async submitReason() {
      if (this.selectedTag.length === 0) {
        this.$message.warning("请选择至少一个反馈问题");
        return;
      }

      if (this.webIMSource === "workbench") {
        this.$socket.emit("rating", {
          record_id: this.msgId,
          score: 2, // 仅点踩事件需要反馈原因
          reasons: this.selectedTag,
        });
      } else {
        this.$clientData.triggerFeedback(this.msgId, this.selectedTag);
        const toastWapper =
          this.webIMSource === "client" && !this.isMobile
            ? document.querySelector(".chat-wrap")
            : document.body;
        this.$toast({
          type: "success",
          message: "感谢你的反馈",
          duration: 3,
          tdom: toastWapper,
        });
      }

      this.feedbackPopupVisible = false;
    },
    // 构建数据
    buildData(d) {
      const {
        record_id,
        related_record_id,
        is_final,
        is_history,
        can_rating,
        can_feedback,
        score,
        reasons,
        is_llm_generated,
        is_connection_error,
        had_retry_qa,
      } = d;
      Object.assign(this, {
        hadRetryQa: had_retry_qa,
        msgId: record_id,
        related_record_id,
        finishWs: is_final,
        isHistory: is_history,
        canRating: can_rating,
        canFeedback: can_feedback,
        ratingScore: score,
        selectedTag: reasons,
        is_llm_generated,
      });

      this.connectionError = is_connection_error;

      if (!d.score || d.score === 0) {
        // 未操作过点赞/点踩
        this.isUpActive = false;
        this.isDownActive = false;
      } else if (d.score === 1) {
        // 已经操作过点赞
        this.isUpActive = true;
      } else if (d.score === 2) {
        // 已经操作过点踩
        this.isDownActive = true;
      }
    },
    // 发送问题（仅限场景：将坐席端右侧搜索结果发送给用户）
    onSendSearchMsg() {
      this.$eventHub.$emit("sendSearchMsg");
    },
    // 复制到输入框
    onCopySearchMsg() {
      this.$eventHub.$emit("copySearchMsg");
    },
    // 重新生成
    onRetryQa() {
      // console.log('onRetryQa', this.webIMSource, this.msgId)
      // console.log(' this.msgList', this.msgList, this.msgData)
      if (this.webIMSource === "workbench") {
        // 坐席端 - 重新触发右侧搜索
        this.$eventHub.$emit("searchMsg");
      } else if (
        this.webIMSource === "client" ||
        this.webIMSource === "manage"
      ) {
        if (this.webIMSource === "client") {
          this.$clientData.hadRetryQa(this.msgId);
        }
        // 用户端 - 查找当前消息关联的问题消息，重新发送问题内容
        const qMsgItem = this.$clientData.getQmsgById(this.msgId);
        this.connectionError = false;

        if (!qMsgItem) {
        } else {
          if (this.webIMSource === "manage") {
            this.$clientData.triggerSendExperienceMsg(
              qMsgItem.content,
              qMsgItem.file_infos || [],
              true
            );
          } else {
            this.$clientData.triggerSendMsg(
              qMsgItem.content,
              qMsgItem.file_infos || []
            );
          }
        }
      }
    },
    // 停止生成
    onStopStream() {
      this.$socket.emit("stop_generation", {
        record_id: this.msgId,
      });

      this.$clientData.modifyMsgContent(this.msgId);
      this.finishWs = true;
    },
    // 打开”去反馈“弹窗
    onOpenFeedback() {
      if (this.webIMSource === "workbench") {
        // 坐席端
        this.feedbackPopupWorkbenchVisible = true;
      } else if (this.webIMSource === "client") {
        // 用户端
        if (this.isMobile) {
          this.feedbackPopupVisible = true;
        } else {
          this.feedbackPopupWorkbenchVisible = true;
        }
      }
    },
    // 修正回复
    onAuditQa() {
      /**
       * 中断状态会添加后缀提示，不应该传给修正编辑框
       */
      const trimMsgContent = (content = "") =>
        content.replace(/<span class="stop-ws">.*?<\/span>/g, "");
      const msg = this.msgData && {
        ...this.msgData,
        content: trimMsgContent(this.msgData.content),
      };
      const payload = JSON.stringify({
        from: "webim",
        type: "audit-create-qa",
        record: msg,
        msgList: this.msgList,
      });
      window.parent.postMessage(payload, "*");
    },
    onCopyMsg() {
      // 复制答案内容 1、过滤md 图片和视频 2、链接格式转换为链接 3、公式原样复制 4、停止生成 去掉 已停止生成文案
      const text = processAndCopyContent(this.msgData.content);
      // 解决iphone复制失效
      setTimeout(() => {
        copy(text);
      }, 0);
      this.$message.success("复制成功");
    },
  },
};
</script>

<style lang="less">
.feedback {
  display: flex;
  align-items: center;
  gap: 8px;
  width: fit-content;
  .h26 {
    height: 26px;
  }
  .opt {
    color: var(--color-text-caption);
    padding: 2px;
    cursor: pointer;

    &:hover {
      color: var(--color-text-secondary);
    }
    &:active {
      color: var(--color-text-primary);
    }
    &.disabled {
      color: var(--color-text-disable);
      cursor: not-allowed;
    }
  }
  .read-history-msg {
    color: var(--color-text-caption);
    img {
      width: 20px;
    }
    cursor: pointer;
    position: relative;
    top: 3px;
    &.disabled {
      svg {
        color: var(--color-text-disable);
        cursor: not-allowed;
      }
    }
  }
  .opt-mobile {
    &:hover {
      color: var(--color-text-caption);
    }
    &:active {
      color: var(--color-text-caption);
    }
  }
  .spliter {
    width: 1px;
    height: 12px;
    background: #d9d9d9;
  }
  .connection-error {
    color: var(--color-error-normal);
    font-size: 12px;
  }

  &-left {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 8px;
  }

  &-right {
    display: flex;
    gap: 12px;
    align-items: center;
  }
  .v-button--small {
    padding: 4px 8px;
  }
}

.feedback-tag-list {
  .feedback-tag-item {
    margin-bottom: 24px;

    .feedback-tag-title {
      font-weight: 400;
      font-size: 14px;
      color: var(--color-text-caption);
    }
    .v-tags {
      line-height: 45px;
    }
  }

  &.isMobile {
    height: calc(100vh / 2);
    overflow-y: overlay; /* 尝试使用 overlay */
    overflow-y: scroll; /* 如果 overlay 不支持，则使用 scroll */
  }
}

.feedback-popup {
  .popup-confirm-btn {
    width: 192px;
  }
}

.feedback-dlg {
  .v-modalDialog__body {
    text-align: left;
  }
}
</style>